package com.zjuh.goodboy.context;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.zjuh.goodboy.awires.AppContextAwire;
import com.zjuh.goodboy.awires.ConfigurationAwire;
import com.zjuh.goodboy.awires.Initializer;
import com.zjuh.goodboy.config.Configuration;
import com.zjuh.goodboy.util.ClassUtil;

public class DefaultAppContext implements AppContext {
	
	private Configuration configuration;

	private Map<String, Object> namedObjects = new HashMap<String, Object>();
	
	public void putObject(String name, Object obj) {
		namedObjects.put(name, obj);
	}
	
	@Override
	public List<?> getObjects(String name) {
		return (List<?>)namedObjects.get(name);
	}

	@Override
	public Object getObject(String name) {
		return namedObjects.get(name);
	}

	private void tryForInterfaces(Object obj) {
		if (obj instanceof ConfigurationAwire) {
			((ConfigurationAwire)obj).setConfiguration(configuration);
		}
		if (obj instanceof AppContextAwire) {
			((AppContextAwire)obj).setAppContext(this);
		}
		if (obj instanceof Initializer) {
			((Initializer)obj).init();
		}
	}
	
	@SuppressWarnings("unchecked")
	private void tryForInterfaces() {
		for (Map.Entry<String, Object> entry : namedObjects.entrySet()) {
			Object obj = entry.getValue();
			if (obj instanceof List) {
				for (Object listElement : (List)obj) {
					tryForInterfaces(listElement);
				}
			} else {
				tryForInterfaces(obj);
			}
		}
	}

	@Override
	public void init(Configuration configuration) {
		this.configuration = configuration;
		for(Map.Entry<String, Class<?>> entry : configuration.getNamedClasses().entrySet()) {
			String name = entry.getKey();
			Class<?> clazz = entry.getValue();
			Object obj = ClassUtil.newInstance(clazz);
			namedObjects.put(name, obj);
		}
		
		for(Map.Entry<String, List<Class<?>>> entry : configuration.getNamedClassList().entrySet()) {
			String name = entry.getKey();
			List<Class<?>> clazzList = entry.getValue();
			List<Object> objectList = new ArrayList<Object>();
			for (Class<?> clazz : clazzList) {
				Object obj = ClassUtil.newInstance(clazz);
				objectList.add(obj);
			}
			namedObjects.put(name, objectList);
		}
		
		tryForInterfaces();
	}

}
